import { gameConfigHandle, propName } from "core/config/gameConfig";
import Random from "core/utils/random";
import utils from "core/utils/utils";
import { BattleInfoModel, DamageDataModel, FighterTeamInfoModel, TriggerEffectDataModel } from "core/model/battleInfoModel";
import { FighterModel } from "core/model/fighterModel";
import { AngerType, HurtType, AttackType, BattleResult, BattleType, BuffPositive, BuffType, MapType, AnimationValueType, TargetRankType, TargetType, TeamID, TriggerType, UnitType } from "core/typeDefine/typeDefine";
import BattleSkillHandle from "./battleSkillHandle";
import TimerHandle from "./timerHandle";
import { FighterSkillModel } from "core/model/skillModel";
import MonsterHandle from "./monsterHandle";
import { BuffModel } from "core/model/buffModel";
import fighterHandle from "core/handle/fighterHandle";
import TimerManager from "./timeManager";

const DamagePosCoe = {
    [UnitType.Boss]: 3,
    [UnitType.Elite]: 2,
    [UnitType.Normal]: 1,
}

export default class BattleHandle {
    partner: FighterModel
    boss: FighterModel
    team1: FighterModel[]
    team2: FighterModel[]
    altar1: FighterModel
    altar2: FighterModel
    aureoles: BuffModel[]
    teamIndexID: number
    rand: Random
    battleQueue: FighterModel[]
    allQueue: FighterModel[]
    battleIndex: number
    update: any
    timeCoe: number
    battleTimer: any
    fighterNodes: any
    battleSkillHandle: BattleSkillHandle
    monsterHandle: MonsterHandle
    team1Hp: number
    battleSpeedByTeam: any
    team2Hp: number
    floor: number
    originFloor: number
    mapID: number
    stage: number = 1
    maxStage: number = 1
    monsterAmountMax: number
    monsterAmount: number
    monsterAliveAmount: number
    team1Length: number
    team2Length: number
    deadIndex: any //记录死亡的索引
    battleType: BattleType
    round: number
    mapType: MapType
    maxRound: number
    dayTime: number
    timerHandle: TimerManager
    maxRow: number = 6 //行
    maxCol: number = 9 //列
    DamagePosAmount: number = 0
    gameEnd: boolean = false
    DamagePosCoe = DamagePosCoe
    fighterBgNodes: any
    monsterLvl: number = 1
    bossX: number = 4
    bossY: number = 1
    bossXY: []
    bossPoss: any = {}
    monsters: Map<number, FighterModel> = new Map()
    monsterDead: any = {}
    weaponNode: any
    addMonsterCd: number
    bossAddMonsterCd: number
    weaponangle: number = 0
    gameType: string = 'round'
    resultCb: any
    otherEffects: any = {}
    timelineData: any = {}
    timelineIndex: number = 1
    altarDamageCoe: number = 1
    totalRoundTime: number = 0
    speedRunTime: number = 0
    statisticsData: any = {}
    weedDay: number = 0
    // reduceHpOfBoss: number = 0
    deadHeros: number[] = []
    damageKillData: any = { damage: {}, kill: {}, hurt: {}, cure: {} }
    enemyDamageData: any = { damage: {}, kill: {} }
    constructor() {
        let battleConfig = gameConfigHandle.gameConfig.battle
        this.maxRow = battleConfig.maxRow
        this.maxCol = battleConfig.maxCol
        this.battleSkillHandle = new BattleSkillHandle(this)
        this.fighterNodes = {}
        this.fighterBgNodes = {}
        this.battleQueue = []
        this.allQueue = []
        this.battleIndex = 0
        this.timeCoe = 1
        this.battleTimer = {}
        this.team1Length = this.maxCol * this.maxRow
        this.team2Length = this.maxCol * this.maxRow
        this.teamIndexID = 20
        this.team1 = new Array(this.team1Length).fill(null)
        this.team2 = new Array(this.team2Length).fill(null)
        this.monsterAliveAmount = 0
        this.monsterAmount = 0
        this.aureoles = []
        this.deadIndex = {}
        this.round = 1
        this.mapType = MapType.Normal
        this.battleSpeedByTeam = {}
        this.timerHandle = new TimerManager()

    }

    async init(fighterTeamInfo1: FighterTeamInfoModel, mapID: number, floor: number, monsterLvl: number, seed: number, altarDamageCoe: number, weedDay: number = 0) {
        this.rand = new Random(seed)
        this.mapID = mapID
        this.weedDay = weedDay
        this.altarDamageCoe = altarDamageCoe
        this.battleType = BattleType.Adventure
        let team1 = fighterTeamInfo1.team
        this.battleSpeedByTeam[TeamID.Team1] = fighterTeamInfo1.battleSpeed
        let mapItemConfig = gameConfigHandle.configByID[mapID]
        this.mapType = mapItemConfig.mapType
        this.monsterAmountMax = utils.getIncValues(mapItemConfig.monsterAmount, floor)
        if (this.monsterAmountMax > mapItemConfig.monsterMaxAmount) {
            this.monsterAmountMax = mapItemConfig.monsterMaxAmount
        }
        this.originFloor = floor
        // if (mapItemConfig.monsterLvlByFloor) {
        //     this.floor = utils.getIncValues(mapItemConfig.monsterLvlByFloor, floor)
        // } else {
        //     this.floor = floor
        // }
        this.monsterLvl = monsterLvl
        this.monsterHandle = new MonsterHandle(this)
        team1.forEach((fighter, i) => {
            if (fighter) {
                fighter.teamIndexID = this.teamIndexID++
                fighter.teamID = TeamID.Team1
                this.allQueue.push(fighter)
                this.battleQueue.push(fighter)
                this.team1[i] = fighter
                fighterHandle.calcSkills(fighter, this)
                fighter.battlePos = i
                this.battleUpdate(1, fighter)
                this.statisticsData[fighter.teamIndexID] = { hurt: 0, cure: 0, recover: 0, beHurt: 0 }
            }
        })
        if (fighterTeamInfo1.altar) {
            this.altar1 = fighterTeamInfo1.altar
            this.altar1.teamID = TeamID.Team1
            this.altar1.teamIndexID = this.teamIndexID++
            this.altar1.battlePos = 12
            this.battleQueue.push(this.altar1)
            fighterHandle.calcSkills(this.altar1, this)
            this.statisticsData[this.altar1.teamIndexID] = { hurt: 0, cure: 0, recover: 0, beHurt: 0 }
            this.battleUpdate(1, this.altar1)
        }


        this.maxStage = mapItemConfig.maxStage || 1
        let monsterTeam = this.monsterHandle.createMonsters(this.rand)
        monsterTeam.team.forEach((fighter, i) => {
            if (fighter) {
                fighter.teamIndexID = this.teamIndexID++
                fighter.teamID = TeamID.Team2
                this.allQueue.push(fighter)
                this.battleQueue.push(fighter)
                this.team2[i] = fighter
                fighterHandle.calcSkills(fighter, this)
                fighter.battlePos = i
                this.statisticsData[fighter.teamIndexID] = { hurt: 0, cure: 0, recover: 0, beHurt: 0 }
                this.battleUpdate(1, fighter)
            }
        })

        // this.boss = monsterTeam.team[0]

        this.maxRound = gameConfigHandle.gameConfig.battle.maxRound[this.mapType]
        this.battleQuqueSortBySpeed()
        await this.battleUpdate(0)

    }
    async initArenaBattle(fighterTeamInfo1: FighterTeamInfoModel, fighterTeamInfo2: FighterTeamInfoModel, seed: number) {
        this.rand = new Random(seed)
        this.mapType = MapType.Arena
        this.battleType = BattleType.Pk
        let team1 = fighterTeamInfo1.team
        let team2 = fighterTeamInfo2.team
        team1.forEach((fighter, i) => {
            if (fighter) {
                fighter.teamIndexID = this.teamIndexID++
                fighter.teamID = TeamID.Team1
                this.battleQueue.push(fighter)
                this.allQueue.push(fighter)
                this.team1[i] = fighter
                fighter.battlePos = i
                fighterHandle.calcSkills(fighter, this)
                this.battleUpdate(1, fighter)
                this.statisticsData[fighter.teamIndexID] = { hurt: 0, cure: 0, recover: 0, beHurt: 0 }
            }
        })
        if (fighterTeamInfo1.altar) {
            this.altar1 = fighterTeamInfo1.altar
            this.altar1.teamIndexID = this.teamIndexID++
            this.altar1.teamID = TeamID.Team1
            this.altar1.battlePos = 12
            this.battleQueue.push(this.altar1)
            fighterHandle.calcSkills(this.altar1, this)
            this.battleUpdate(1, this.altar1)
            this.statisticsData[this.altar1.teamIndexID] = { hurt: 0, cure: 0, beHurt: 0 }
        }

        team2.forEach((fighter, i) => {
            if (fighter) {
                fighter.teamIndexID = this.teamIndexID++
                fighter.teamID = TeamID.Team2
                this.battleQueue.push(fighter)
                this.allQueue.push(fighter)
                this.team2[i] = fighter
                fighter.battlePos = i
                fighterHandle.calcSkills(fighter, this)
                this.battleUpdate(1, fighter)
                this.statisticsData[fighter.teamIndexID] = { hurt: 0, cure: 0, recover: 0, beHurt: 0 }
            }
        })
        if (fighterTeamInfo2.altar) {
            this.altar2 = fighterTeamInfo2.altar
            this.altar2.teamIndexID = this.teamIndexID++
            this.altar2.teamID = TeamID.Team2
            this.altar2.battlePos = 12
            this.battleQueue.push(this.altar2)
            fighterHandle.calcSkills(this.altar2, this)
            this.battleUpdate(1, this.altar2)
            this.statisticsData[this.altar2.teamIndexID] = { hurt: 0, cure: 0, beHurt: 0 }
        }

        this.maxRound = gameConfigHandle.gameConfig.battle.maxRound[this.mapType]
    }
    setUpdate(update) {
        this.update = update
    }
    setTimeCoe(timeCoe) {
        this.timeCoe = timeCoe
        this.timerHandle.setAllSpeed(timeCoe)
        Object.values(this.timelineData).forEach((item: any) => {
            if (item) {
                item.timeScale(timeCoe)
            }
        })
    }
    async start() {
        let battleConfig = gameConfigHandle.gameConfig.battle
        this.gameType = battleConfig.gameType
        if (battleConfig.gameType == 'round') {
            this.roundGameStart()
        } else {
            this.notRoundGameStart()
        }
        return new Promise((resolve, reject) => {
            this.resultCb = (res) => {
                resolve(res)
            }
        })
    }
    async roundGameStart() {
        await this.battleStart()
        await this.setBattleTimeout(200)
        await this.roundStart()
        await this.setBattleTimeout(200)
        await this.battleUpdate(0)
        while (this.round < this.maxRound + 1 && this.isTeamAlive(TeamID.Team1)
            && this.isTeamAlive(TeamID.Team2)) {
            let attacker = this.battleQueue[this.battleIndex]
            if (attacker && attacker.battleAttris.hp >= 1) {
                await this.startAttack(attacker)
                await this.setBattleTimeout(400)
            }
            this.battleIndex += 1
            if (this.battleIndex > this.battleQueue.length - 1) {
                await this.roundEnd()
                await this.setBattleTimeout(100)
                await this.roundSettlement()
                await this.setBattleTimeout(200)
                this.round += 1
                if (!this.isTeamAlive(TeamID.Team1)) {
                    break
                }
                if (!this.isTeamAlive(TeamID.Team2)) {
                    break
                }
                await this.battleUpdate(0)
                this.battleIndex = 0
                await this.roundStart()
                let texts = []
                this.team1.forEach(fighter => {
                    if (fighter) {
                        texts.push(propName[fighter.tid] + "  " + fighter.battleAttris.hp + "/" + fighter.battleAttris.anger + "/" + fighter.battleAttris.shield)
                    }
                })
            }
        }

        if (this.round >= this.maxRound + 1) {
            this.gameOver(BattleResult.Lost)
        }

        if (!this.isTeamAlive(TeamID.Team1)) {
            this.gameOver(BattleResult.Lost)
        }
        if (!this.isTeamAlive(TeamID.Team2)) {
            this.gameOver(BattleResult.Win)
        }

    }
    async notRoundGameStart() {
        this.allQueue.forEach((fighter, i) => {
            this.fighterStart(fighter)
        })

    }
    fighterStart = (attacker: FighterModel) => {
        this.timerHandle.setTimeout(() => {
            this.startAttackByAttackSpeed(attacker)
            // this.recoverHpMp(attacker)
            // for (let i = 0; i < attacker.skills.length; i++) {
            //     let skill = attacker.skills[i]
            //     if (skill && skill.cd > 0) {
            //         this.battleSkillHandle.startUseSkill(attacker, skill)
            //     }
            // }
            let timer = this.timerHandle.setInterval(() => {
                this.calcBuffStatus(attacker)
            }, 5000)
            attacker.timerObject['calcBuffStatus'] = timer
        }, 1)

    }
    adjustBattleQueue = () => {
        this.battleQueue = []
        this.team1.forEach((fighter, i) => {
            if (fighter) {
                this.battleQueue.push(fighter)
                fighter.battlePos = i
            }
        })
        this.team2.forEach((fighter, i) => {
            if (fighter) {
                this.battleQueue.push(fighter)
                fighter.battlePos = i
            }
        })

    }
    battleStart = async () => {
        for (let i = 0; i < this.battleQueue.length; i++) {
            let attacker = this.battleQueue[i]
            await this.battleSkillHandle.triggerEffects(attacker, TriggerType.BattleStart, null, new TriggerEffectDataModel())
        }
    }
    roundStart = async () => {
        let newBattleQueue: FighterModel[] = []
        for (let i = 0; i < this.battleQueue.length; i++) {
            let attacker = this.battleQueue[i]
            if (attacker && attacker.battleAttris.hp >= 1) {
                await this.battleSkillHandle.triggerEffects(attacker, TriggerType.RoundStart, null, new TriggerEffectDataModel())
                newBattleQueue.push(attacker)
            }
        }
        this.battleQueue = newBattleQueue
    }
    roundEnd = async () => {
        for (let i = 0; i < this.battleQueue.length; i++) {
            let attacker = this.battleQueue[i]
            if (attacker && attacker.battleAttris.hp >= 1) {
                //世界boss获得进化
                // if (this.mapID == 300202 && attacker.teamID == TeamID.Team2) {
                //     this.battleSkillHandle.addBuff(null, attacker, 280014, 1, 0, {}, new TriggerEffectDataModel())
                // }

                await this.battleSkillHandle.triggerEffects(attacker, TriggerType.RoundEnd, null, new TriggerEffectDataModel())
            }
        }
    }


    async startAttackByAttackSpeed(attacker: FighterModel) {
        if (attacker && attacker.battleAttris.hp >= 1 && attacker.battleAttris.attackSpeed !== 0) {
            let attackSpeed = this.getAttackInterval(attacker.battleAttris.attackSpeed || 100)
            this.startAttackAnimation(attacker.teamIndexID, attackSpeed / 1000)
            let timerID = this.timerHandle.setTimeout(() => {
                let battleConfig = gameConfigHandle.gameConfig.battle
                this.attackPre(attacker, attacker.normalAttackData || battleConfig.defaultAttackData)
                this.startAttackByAttackSpeed(attacker)
            }, () => {
                let interval = this.getAttackInterval(attacker.battleAttris.attackSpeed || 100)
                return interval
            })
            attacker.timerObject['attack'] = timerID
        }
    }

    startAttack = async (attacker: FighterModel) => {
        if (attacker.status[BuffType.Ice] || attacker.status[BuffType.Vertigo]) {
            return
        }

        let skillConfig = gameConfigHandle.gameConfig.skill
        let skillNeedAnger = Math.floor(skillConfig.skillNeedAnger * (1 - attacker.battleAttris.skillReduceAngerPer / 100))
        // console.log(propName[attacker.tid], '怒气消耗', skillNeedAnger)
        if (skillNeedAnger < skillConfig.skillNeedAngerMin) {
            skillNeedAnger = skillConfig.skillNeedAngerMin
        }
        if (attacker.unitType !== UnitType.Altar && attacker.battleAttris.anger >= skillNeedAnger && attacker.skills[0]
            && !attacker.status[BuffType.Silent]) {
            await this.battleSkillHandle.useSkill(attacker.skills[0], attacker)
        } else {
            let battleConfig = gameConfigHandle.gameConfig.battle
            let attackData = utils.assign({}, battleConfig.defaultAttackData, attacker.normalAttackData)
            if (attacker.normalAttackData) {
                let hartedData = utils.assign({}, battleConfig.defaultAttackData.hartedData, attacker.normalAttackData)
                attackData.hartedData = hartedData
            }
            await this.attackPre(attacker, attackData, 1, new TriggerEffectDataModel({}))
        }
    }
    //攻击后
    async attackPre(attacker: FighterModel, attackDataConfig, lvl: number = 1, triggerEffectPreData?: TriggerEffectDataModel, angerValue: number = 100, defenders?: FighterModel[]) {
        if (attackDataConfig.attackType == AttackType.Normal) {
            this.addAnger(attacker, AngerType.Attack)
        }

        this.attackAnimation(attacker.teamIndexID, triggerEffectPreData.skill ? triggerEffectPreData.skill.tid : null)
        let triggerEffectData = new TriggerEffectDataModel(triggerEffectPreData)
        triggerEffectData.attackType = attackDataConfig.attackType
        triggerEffectData.hurtType = attacker.hurtType
        await this.battleSkillHandle.triggerEffects(attacker, TriggerType.AttackPre, null, triggerEffectData)

        if (attackDataConfig.hartedData || !defenders) {
            defenders = this.calcHatred(this.getOpponentTeamID(attacker.teamID), attackDataConfig.hartedData, lvl, attacker.battlePos)
        }
        let hurtPer = utils.getIncValues(attackDataConfig.hurtPer || [100, 0], lvl)
        if (attackDataConfig.hurtIsShare == true) {
            hurtPer = hurtPer / defenders.length
            if (attackDataConfig.maxHurtPer && hurtPer > attackDataConfig.maxHurtPer) {
                hurtPer = attackDataConfig.maxHurtPer
            }
        }

        let totalDamage = 0
        for (let i = 0; i < defenders.length; i++) {
            let defender = defenders[i]
            let attackTimes = 1 //单体攻击次数
            // if (attackDataConfig.attackTimes) {
            //     let times = attackDataConfig.attackTimes[lvl]
            //     attackTimes = utils.getRandomNumber(times[0], times[1], this.rand)
            // }
            for (let j = 0; j < attackTimes; j++) {
                let preAttackData = new DamageDataModel({
                    ...triggerEffectPreData,
                    attackType: attackDataConfig.attackType,
                    hurtType: attacker.hurtType,
                    hurtPer: hurtPer,
                    angerValue,
                    decHpName: attackDataConfig.decHpName || '',
                })
                if (attackDataConfig.hurtDec) { //伤害递减
                    preAttackData.hurtDec = attackDataConfig.hurtDec * i
                }
                if (attackDataConfig.hurtInc) { //伤害递增
                    preAttackData.hurtInc = attackDataConfig.hurtInc * i
                }
                if (attackDataConfig.breakShieldPer) { //击碎目标护盾
                    preAttackData.breakShieldPer = utils.getIncValues(attackDataConfig.breakShieldPer, lvl)
                }
                if (attackDataConfig.hpHurtPer) { // 造成目标最大生命百分比的伤害
                    preAttackData.hpHurtPer = utils.getIncValues(attackDataConfig.hpHurtPer, lvl)
                }
                if (attackDataConfig.attackerHpHurtPer) {  // 造成攻击者的最大生命百分比的伤害
                    preAttackData.attackerHpHurtPer = utils.getIncValues(attackDataConfig.attackerHpHurtPer, lvl)
                }

                if (attackDataConfig.negativeHurtPer) {  // 负面状态伤害
                    preAttackData.negativeHurtPer = attackDataConfig.negativeHurtPer
                }
                if (attackDataConfig.maxNegativeHurtPer) {  // 负面状态总伤害上限
                    preAttackData.maxNegativeHurtPer = attackDataConfig.maxNegativeHurtPer
                }

                let damageData = await this.calcPreDamage(attacker, defender, preAttackData)
                totalDamage += damageData.damage
            }
        }
        if (attacker.battleAttris.bloodRate > 0) {
            let hp = Math.floor(attacker.battleAttris.bloodRate * totalDamage / 100)
            this.addHp(attacker, hp, AnimationValueType.BloodHp)
        }
        await this.battleSkillHandle.triggerEffects(attacker, TriggerType.AttackAfter, null, new TriggerEffectDataModel({ ...triggerEffectData, damage: totalDamage }))
    }
    //攻击后
    async calcPreDamage(attacker: FighterModel, defender: FighterModel, preAttackData: DamageDataModel): Promise<DamageDataModel> {

        await this.battleSkillHandle.triggerEffects(attacker, TriggerType.CalcDamagePre, defender,
            new TriggerEffectDataModel(preAttackData))
        if (preAttackData.attackType == AttackType.Normal || preAttackData.attackType == AttackType.Skill) {
            this.addAnger(defender, AngerType.BeAttack)
        }
        let damageData = await this.calcDamage(attacker, defender, preAttackData)
        await this.decHp(defender, attacker, damageData)
        if (damageData.isBlock) {
            await this.battleSkillHandle.triggerEffects(defender, TriggerType.Block, defender,
                new TriggerEffectDataModel(damageData))
        }
        //造成伤害后
        await this.battleSkillHandle.triggerEffects(attacker, TriggerType.CalcDamageAfter, defender,
            new TriggerEffectDataModel(damageData))

        //连击
        if (preAttackData.attackType == AttackType.Normal && defender.battleAttris.hp >= 1 && attacker.battleAttris.doubleAttack > 0) {
            await this.doubleAttack(attacker, defender)
        }
        return damageData

        //反击
        // if (defender.battleAttris.attackBackPer > 0 && preAttackData.attackType == AttackType.Normal) {
        //     if (this.rand.intn(100) < defender.battleAttris.attackBackPer) {
        //         await this.setBattleTimeout(150)
        //         let _preAttackData = new DamageDataModel({ attackType: AttackType.AttackBack, hurtType: defender.hurtType })
        //         await this.calcPreDamage(defender, attacker, _preAttackData)
        //     }
        // }
    }

    clickAttack = async (defenderTeamIndexID: number) => {
        let opponentTeamID = this.getOpponentTeamID(defenderTeamIndexID)
        let altar = this.getAltarFighterByTeamIndexID(opponentTeamID)
        if (!altar) {
            return
        }
        if (altar.battleAttris.hp <= 1) {
            return
        }
        let defender = this.getFighterByTeamIndexID(defenderTeamIndexID)
        if (defender && defender.battleAttris.hp < 1) {
            return
        }
        let damageData = new DamageDataModel({ damage: altar.battleAttris.attack, attackHurtType: HurtType.Holy })
        damageData.decHpName = '神圣'
        altar.battleAttris.hp -= 1
        this.attackAnimation(altar.teamIndexID)
        await this.decHp(defender, altar, damageData)
    }

    doubleAttack = async (attacker: FighterModel, defender: FighterModel) => {
        let maxAttackTimes = Math.ceil(attacker.battleAttris.doubleAttack / 100)
        let attackTimes = 0
        let doubleAttack = attacker.battleAttris.doubleAttack
        while (attackTimes < maxAttackTimes) {
            let per = doubleAttack / (doubleAttack + 50 + attackTimes * 100) * 100
            if (this.rand.intn(100) < per) {
                attackTimes += 1
            } else {
                break
            }
        }
        if (attackTimes >= 1) {
            this.doubleAnimation(attacker.teamIndexID, attackTimes)
        }
        for (let j = 0; j < attackTimes; j++) {
            await this.setBattleTimeout(150)
            let _preAttackData = new DamageDataModel({ attackType: AttackType.DoubleAttack })
            await this.calcPreDamage(attacker, defender, _preAttackData)
        }
    }

    //计算攻击伤害
    async calcDamage(attacker: FighterModel, defender: FighterModel, preDamageData: DamageDataModel) {
        let damageData = new DamageDataModel(preDamageData)

        if (attacker.unitType == UnitType.Altar && preDamageData.attackType == AttackType.Normal) {
            damageData.damage = attacker.battleAttris.attack * this.altarDamageCoe
            damageData.decHpName = '神圣'
            // if (this.mapID == 300202) {
            //     console.log('幻界',attacker.battleAttris.attack,damageData.damage)
            // }else{
            //     console.log('过图',attacker.battleAttris.attack,damageData.damage)
            // }

            return damageData
        }
        if (defender.unitType == UnitType.Altar) {
            damageData.damage = 1
            return damageData
        }

        let isDodge = await this.calcDodge(attacker, defender, false)
        damageData.isDodge = isDodge
        if (isDodge) {
            damageData.damage = 0
            return damageData
        }

        let { isBlock, blockReduceHurt } = this.calcBlock(attacker, defender)
        damageData.isBlock = isBlock

        let { isCrit, critHurt } = await this.calcCrit(attacker, defender, damageData)
        damageData.isCrit = isCrit
        let baseValue = attacker.battleAttris.attack
        if (attacker.unitType == UnitType.Altar) {
            let { totalAttack } = this.getAltarAttack(attacker.teamID)
            baseValue = totalAttack
        }
        let defRatio = this.calcDefRatio(attacker, defender)

        let skillHurtPer = damageData.hurtPer
        if (damageData.attackType == AttackType.Skill) {
            skillHurtPer = skillHurtPer + attacker.battleAttris.skillHurtPer - defender.battleAttris.antiSkillHurtPer
            if (damageData.skill) {
                skillHurtPer += damageData.skill.hurtPer
            }
        }
        let hurtPer = attacker.battleAttris.hurtPer - defender.battleAttris.antiHurtPer
        if (hurtPer < -70) {
            hurtPer = -70
        }
        let hurt = baseValue * defRatio *
            (skillHurtPer / 100) *
            (1 + hurtPer / 100) *
            (1 + critHurt / 100) *
            (1 + defender.battleAttris.beHurtPer / 100) *
            (1 - damageData.hurtDec / 100) *
            (1 - blockReduceHurt / 100)

        if (defender.unitType == UnitType.Boss || defender.unitType == UnitType.Partner) {
            hurt *= (1 + attacker.battleAttris.elitePer / 100)
        }

        //状态增加伤害
        utils.entries(attacker.statusHurtPer).forEach(item => {
            let statuId = item[0]
            let value: any = item[1]
            if (defender.status[statuId]) {
                hurt *= (1 + value / 100)
            }
        })

        //状态减伤害
        utils.entries(defender.statusReduceHurt).forEach(item => {
            let statuId = item[0]
            let value: any = item[1]
            if (attacker.status[statuId]) {
                hurt *= (1 - value / 100)
            }
        })

        if (damageData.skill) {
            hurt *= (1 + (damageData.angerValue - 100) / 5 / 100) //怒气超过100时，每5点怒气提升1%伤害
            let skillID = damageData.skill.tid
            //技能增加伤害
            if (attacker.skillsHurtPer[skillID]) {
                hurt *= (1 + attacker.skillsHurtPer[skillID] / 100)
            }
        }
        if (damageData.negativeHurtPer) { // 每一个负面状态提升伤害

            let amount = 0
            defender.buffs.forEach(buff => {
                let buffConfig = gameConfigHandle.configByID[buff.tid]
                if (buffConfig.positive == BuffPositive.Negative) {
                    amount += 1
                }
            })
            let addHurt = damageData.negativeHurtPer * amount
            if (damageData.maxNegativeHurtPer) {
                if (addHurt > damageData.maxNegativeHurtPer) {
                    addHurt = damageData.maxNegativeHurtPer
                }
            } else if (addHurt > 500) {
                addHurt = 500
            }

            hurt *= (1 + addHurt / 100)

        }

        if (damageData.hpHurtPer) { // 造成最大生命百分比的伤害,不超过攻击力的10倍
            let value = defender.battleAttris.maxHp * damageData.hpHurtPer / 100
            if (attacker.unitType == UnitType.Altar) {
                if (value >= baseValue * 2) {
                    value = baseValue * 2
                }
            } else {
                if (value >= baseValue * 10) {
                    value = baseValue * 10
                }
            }

            hurt += value
        }

        if (attacker.battleAttris.hpHurtPer) { // 造成最大生命百分比的伤害,不超过攻击力的10倍
            let value = defender.battleAttris.maxHp * attacker.battleAttris.hpHurtPer / 100
            if (attacker.unitType == UnitType.Altar) {
                if (value >= baseValue * 2) {
                    value = baseValue * 2
                }
            } else {
                if (value >= baseValue * attacker.battleAttris.hpMaxHurtCoe) {
                    value = baseValue * attacker.battleAttris.hpMaxHurtCoe
                }
            }
            hurt += value
        }
        if (damageData.attackerHpHurtPer) { // 攻击者造成最大生命百分比的伤害
            hurt += attacker.battleAttris.maxHp * damageData.hpHurtPer / 100
        }

        if (hurt < 1) {
            hurt = 1
        }

        hurt = Math.floor(hurt)
        damageData.damage = hurt
        return damageData
    }
    async calcDodge(attacker: FighterModel, defender: FighterModel, isSkill: boolean = false) {
        // let hit = attacker.battleAttris.hit + 30
        // let dodge = defender.battleAttris.dodge + 30
        // let hitCoe = (35 * hit / dodge)
        // if (hitCoe > 35) {
        //     hitCoe = 35
        // }
        // let dodgeRatio = (dodge / (hit + dodge) * 100 - hitCoe)
        // if (dodgeRatio > 85) {
        //     dodgeRatio = 85
        // }
        // if (attackTye == AttackType.Skill) {
        //     dodgeRatio = Math.floor(dodgeRatio * 0.75)
        // }
        // let isDodge = dodgeRatio > this.rand.intn(100) ? true : false
        // if (isDodge) {
        //     return isDodge
        // } else {
        //     return isDodge
        // }
        if (defender.unitType == UnitType.Altar || attacker.unitType == UnitType.Altar) {
            return false
        }
        let dodgeRatio = defender.battleAttris.dodgeRate - attacker.battleAttris.hitRate
        if (isSkill) {
            dodgeRatio = dodgeRatio * 0.5
        }
        let isDodge = dodgeRatio > this.rand.intn(100) ? true : false
        if (isDodge) {
            return isDodge
        } else {
            return isDodge
        }
    }
    calcBlock(attacker: FighterModel, defender: FighterModel) {
        let rate = defender.battleAttris.blockRate - attacker.battleAttris.antiBlockRate
        if (rate > 90) {
            rate = 90
        }
        let r = this.rand.intn(100)
        if (r < rate) {
            return { isBlock: true, blockReduceHurt: gameConfigHandle.gameConfig.battle.blockReduceHurt }
        }
        return { isBlock: false, blockReduceHurt: 0 }
    }
    async calcCrit(attacker: FighterModel, defender: FighterModel, preDamageData: DamageDataModel) {
        // let cirt = attacker.battleAttris.crit + 30
        // let antiCrit = defender.battleAttris.antiCrit + 30
        // let critCoe = (35 * antiCrit / cirt)
        // if (critCoe > 35) {
        //     critCoe = 35
        // }
        // let critRatio = (100 - antiCrit / (cirt + antiCrit) * 100 - critCoe)
        // if (critRatio < 5) {
        //     critRatio = 5
        // }

        let critRatio = attacker.battleAttris.critRate - defender.battleAttris.antiCritRate + 5
        // if (preDamageData.skill) {
        //     critRatio = attacker.battleAttris.scritRate + preDamageData.skill.scritRate - defender.battleAttris.antiScritRate + 5
        // }
        let r = this.rand.intn(100)
        if (r < critRatio) {
            // if (preDamageData.skill) {
            //     let critHurt = attacker.battleAttris.scritHurtPer + 50 + preDamageData.skill.scritHurtPer
            //     let antiCritHurt = defender.battleAttris.antiSCritHurtPer
            //     let critValue = critHurt - antiCritHurt
            //     if (critValue < 25) {
            //         critValue = 25
            //     }
            //     return { isCrit: true, critHurt: critValue }
            // } else {
            let critHurt = attacker.battleAttris.critHurtPer + 50
            let antiCritHurt = defender.battleAttris.antiCritHurtPer
            let critValue = critHurt - antiCritHurt
            if (critValue < 50) {
                critValue = 50
            }
            return { isCrit: true, critHurt: critValue }
            // }

        } else {
            return { isCrit: false, critHurt: 0 }
        }
    }

    calcDefRatio(attacker: FighterModel, defender: FighterModel) {
        let attack = attacker.battleAttris.attack + 10
        let def = defender.battleAttris.def + 10
        let breakDefRate = attacker.battleAttris.breakDefRate - defender.battleAttris.antiBreakDefRate
        if (breakDefRate < 0) {
            breakDefRate = 0
        }
        if (breakDefRate > 70) {
            breakDefRate = 70
        }
        def = def - (def * breakDefRate / 100)
        // //减伤率 = 100 - 穿刺/(穿刺+物防)x100 - (35x穿刺/物防)
        // let defCoe = (35 * puncture / def)
        // if (defCoe > 35) {
        //     defCoe = 35
        // }
        // let defRatio = (100 - puncture / (puncture + def) * 100 - defCoe) / 100
        // if (defRatio > 0.85) {
        //     defRatio = 0.85
        // }
        let defRatio = attack / (attack + def)
        return defRatio
    }


    //angerType 0 攻击, 1被攻击, 2回合结束
    addAnger(affecteder: FighterModel, angerType: AngerType) {
        let { y } = this.getXY(affecteder.battlePos)
        let battleConfig = gameConfigHandle.gameConfig.battle
        let getAngerConfig = battleConfig.getAnger
        let anger = getAngerConfig[y][angerType]
        affecteder.battleAttris.anger += anger
        if (affecteder.battleAttris.anger > battleConfig.maxAnger) {
            affecteder.battleAttris.anger = battleConfig.maxAnger
        }
        // this.fighterNodeUpdate(affecteder.teamIndexID)
        // let getAnger = affecteder.battleAttris.attackMp
        // if (attackType == AttackType.DoubleAttack) {
        //     getAnger = Math.floor(battleConfig.doubleGetAngerPer * getAnger / 100)
        // }
        // affecteder.battleAttris.mp += getAnger
        // if (affecteder.battleAttris.mp > affecteder.battleAttris.maxMp) {
        //     affecteder.battleAttris.mp = affecteder.battleAttris.maxMp
        // }
        this.fighterNodeUpdate(affecteder.teamIndexID)
        // this.battleSkillHandle.playSkill(affecteder)
    }

    async decHp(affecteder: FighterModel, attacker: FighterModel, damageData: DamageDataModel) {
        if (affecteder.battleAttris.hp < 1) {
            return
        }
        let value = Math.floor(damageData.damage || 0)
        if (this.statisticsData[affecteder.teamIndexID]) {
            this.statisticsData[affecteder.teamIndexID].beHurt += value
        }
        if (attacker && this.statisticsData[attacker.teamIndexID]) {
            this.statisticsData[attacker.teamIndexID].hurt += value
        }
        if (affecteder.battleAttris.shield > 0) {
            if (damageData.breakShieldPer) {
                affecteder.battleAttris.shield = Math.floor(affecteder.battleAttris.shield * (100 - damageData.breakShieldPer) / 100)
            }
            if (affecteder.battleAttris.shield > value) {
                affecteder.battleAttris.shield -= value
            } else {
                affecteder.battleAttris.hp -= value - affecteder.battleAttris.shield
                affecteder.battleAttris.shield = 0
                await this.battleSkillHandle.triggerEffects(null, TriggerType.OtherClearShield, affecteder, new TriggerEffectDataModel(damageData))
            }
        } else {
            affecteder.battleAttris.hp -= value
        }
        if (affecteder.battleAttris.hp < 1) {
            affecteder.battleAttris.hp = 0
        }

        //幻界伤害统计
        // if (this.mapID == 300202 && affecteder.teamID == TeamID.Team2) {
        //     this.reduceHpOfBoss += value
        // }

        //我方阵亡统计
        if (affecteder.battleAttris.hp < 1 && affecteder.teamID == TeamID.Team1) {
            if (!this.deadHeros.includes(affecteder.tid) && affecteder.tid !== 320100) {
                this.deadHeros.push(affecteder.tid)
                if (gameConfigHandle.gameConfig.luck.frontMaps.includes(this.mapID)) {
                }
            }
        }

        //伤害统计
        this.calcDamageData(attacker, affecteder, value, damageData)

        this.beAttackAnimation(affecteder.teamIndexID, damageData)

        //被攻击后
        await this.battleSkillHandle.triggerEffects(affecteder, TriggerType.BeInjured, attacker,
            new TriggerEffectDataModel(damageData))

        //被攻击后
        await this.battleSkillHandle.triggerEffects(null, TriggerType.OtherBeInjured, affecteder,
            new TriggerEffectDataModel(damageData))

        if (affecteder.battleAttris.hp < 1) {
            affecteder.battleAttris.hp = 0
            if (attacker) {
                await this.battleSkillHandle.triggerEffects(attacker, TriggerType.KillEnemy, affecteder, new TriggerEffectDataModel(damageData))
            }
            await this.battleSkillHandle.triggerEffects(affecteder, TriggerType.Dead, attacker, new TriggerEffectDataModel(damageData))
            await this.battleSkillHandle.triggerEffects(null, TriggerType.OtherDead, affecteder, new TriggerEffectDataModel(damageData))

            if (!this.deadIndex[affecteder.teamIndexID]) {
                this.deadIndex[affecteder.teamIndexID] = true
                utils.values(affecteder.timerObject).forEach(timerID => {
                    this.timerHandle.clear(timerID)
                })
                affecteder.timers.forEach(timerID => {
                    this.timerHandle.clear(timerID)
                })
                this.disappearAnimation(affecteder.teamIndexID)
                this.battleUpdate(0)
                if (!this.isTeamAlive(affecteder.teamID)) {
                    this.timerHandle.stop()
                    if (this.gameEnd == false) {
                        this.gameEnd = true
                        if (affecteder.teamID == TeamID.Team2) {
                            this.gameOver(BattleResult.Win)
                        } else {
                            this.gameOver(BattleResult.Lost)
                        }
                    }
                } else if (this.isNextStage(affecteder.teamID)) {
                    await this.nextStage(affecteder.teamID)
                }
            }
        }
        return value
    }

    calcDamageData(attacker: FighterModel, affecteder: FighterModel, value, damageData) {
        //伤害统计
        if (affecteder.teamID == TeamID.Team2) {
            this.damageKillData.damage['all'] = (this.damageKillData.damage['all'] || 0) + value

            // if(this.mapID == 300202){
            //     console.log('当前累计伤害',this.damageKillData.damage['all'],utils.getNumberText(this.damageKillData.damage['all']))
            // }

            if (affecteder.battleAttris.hp < 1) {
                this.damageKillData.kill['all'] = (this.damageKillData.kill['all'] || 0) + 1
            }
            if (attacker == null || attacker == undefined) {//持续伤害
                // this.damageKillData.damage[damageData.hurtType] = (this.damageKillData.damage[damageData.hurtType] || 0) + value
                // if (affecteder.battleAttris.hp < 1) {
                //     this.damageKillData.kill[damageData.hurtType] = (this.damageKillData.kill[damageData.hurtType] || 0) + 1
                // }

            } else {//直接伤害
                this.damageKillData.damage[attacker.tid] = (this.damageKillData.damage[attacker.tid] || 0) + value
                if (affecteder.battleAttris.hp < 1) {
                    this.damageKillData.kill[attacker.tid] = (this.damageKillData.kill[attacker.tid] || 0) + 1
                }
            }
        }
        //敌方伤害统计
        if (affecteder.teamID == TeamID.Team1) {
            //我方受伤统计
            this.damageKillData.hurt['all'] = (this.damageKillData.hurt['all'] || 0) + value
            this.damageKillData.hurt[affecteder.tid] = (this.damageKillData.hurt[affecteder.tid] || 0) + value

            this.enemyDamageData.damage['all'] = (this.enemyDamageData.damage['all'] || 0) + value
            if (affecteder.battleAttris.hp < 1) {
                this.enemyDamageData.kill['all'] = (this.enemyDamageData.kill['all'] || 0) + 1
            }
            if (attacker == null || attacker == undefined) {//持续伤害
                // this.enemyDamageData.damage[damageData.hurtType] = (this.enemyDamageData.damage[damageData.hurtType] || 0) + value
                // if (affecteder.battleAttris.hp < 1) {
                //     this.enemyDamageData.kill[damageData.hurtType] = (this.enemyDamageData.kill[damageData.hurtType] || 0) + 1
                // }

            } else {//直接伤害
                this.enemyDamageData.damage[attacker.tid] = (this.enemyDamageData.damage[attacker.tid] || 0) + value
                if (affecteder.battleAttris.hp < 1) {
                    this.enemyDamageData.kill[attacker.tid] = (this.enemyDamageData.kill[attacker.tid] || 0) + 1
                }
            }
        }
    }

    async gameOver(result: BattleResult) {
        this.timerHandle.stop()
        // if (this.mapID == 300202) {
        //     console.log('幻界boss掉血=', this.team2[0].battleAttris.maxHp - this.team2[0].battleAttris.hp)
        // }

        this.resultCb && this.resultCb({
            result: result, monsterAmount: this.monsterAmount,
            monsterAmountMax: this.monsterAmountMax, monsterAliveAmount: this.monsterAliveAmount, round: this.round, totalRunTime: this.totalRoundTime, speedRunTime: this.speedRunTime,
            // reduceHpOfBoss: this.reduceHpOfBoss, 
            reduceHpOfBoss: this.damageKillData.damage['all'],
            deadHeros: this.deadHeros
        })
    }

    //恢复生命和魔法
    async recoverHpMp(attacker: FighterModel) {
        let battleConfig = gameConfigHandle.gameConfig.battle
        let timerID = this.timerHandle.setInterval(() => {
            if (attacker.battleAttris.hp >= 1) {
                let recoverValue = attacker.battleAttris.recoverHp
                if (recoverValue > 0) {
                    let damageData = new DamageDataModel()
                    damageData.addHpName = '恢复'
                    this.addHp(attacker, recoverValue, AnimationValueType.RecoverHp)
                }
            }
        }, battleConfig.recoverHpCd)
        attacker.timerObject['recoverHp'] = timerID
        if (attacker.unitType == UnitType.Partner) {
            let timerID = this.timerHandle.setInterval(() => {
                if (attacker.battleAttris.hp >= 1) {
                    let recoverValue = attacker.battleAttris.recoverMp
                    if (recoverValue > 0) {
                        let damageData = new DamageDataModel()
                        damageData.addHpName = '恢复魔法'
                        this.addMp(attacker, recoverValue, '恢复魔法')
                    }
                }
            }, battleConfig.recoverMpCd)
            attacker.timerObject['recoverMp'] = timerID
        }

    }

    getAltarAttack(teamID: TeamID) {
        let team = this.getTeam(teamID)
        let totalAttack = 0
        for (let i = 0; i < team.length; i++) {
            let fighter = team[i]
            if (fighter) {
                totalAttack += fighter.battleAttris.attack
            }
        }
        let aveAttack = Math.floor(totalAttack / 5)
        return { totalAttack, aveAttack }
    }

    addHp(affecteder: FighterModel, value: number, addType: AnimationValueType = AnimationValueType.RecoverHp, str: string = null) {
        value = Math.floor(value)
        if (affecteder.battleAttris.recoverPer) {
            value = Math.floor(value * (1 + affecteder.battleAttris.recoverPer / 100))
            if (value < 1) {
                value = 1
            }
        }
        if (affecteder.battleAttris.recoverCurePer) {
            value = Math.floor(value * (1 + affecteder.battleAttris.recoverCurePer / 100))
            if (value < 1) {
                value = 1
            }
        }
        this.statisticsData[affecteder.teamIndexID].recover += value
        affecteder.battleAttris.hp += value
        if (affecteder.battleAttris.hp > affecteder.battleAttris.maxHp) {
            affecteder.battleAttris.hp = affecteder.battleAttris.maxHp
        }

        this.recoverAnimation(affecteder.teamIndexID, value, addType, str)
        return value
    }

    addMp(affecteder: FighterModel, value: number, str: string = null, isCrit: boolean = false) {
        affecteder.battleAttris.mp += value
        if (affecteder.battleAttris.mp > affecteder.battleAttris.maxMp) {
            affecteder.battleAttris.mp = affecteder.battleAttris.maxMp
        }
        this.recoverMpAnimation(affecteder.teamIndexID, value, str, isCrit)
        return value
    }


    async roundSettlement() {
        //回合结束触发
        for (let i = 0; i < this.battleQueue.length; i++) {
            let fighter = this.battleQueue[i]
            if (fighter && fighter.battleAttris.hp >= 1) {
                await this.roundSettlementOnce(fighter)
            }
        }
    }
    async roundSettlementOnce(fightAttrier: FighterModel) {
        let recoverValue = fightAttrier.battleAttris.recoverHp
        if (fightAttrier.battleAttris.recoverPer) {
            recoverValue += Math.floor(fightAttrier.battleAttris.recoverPer * fightAttrier.battleAttris.maxHp / 100)
        }
        if (recoverValue > 0) {
            this.addHp(fightAttrier, recoverValue, AnimationValueType.RecoverHp)
        }
        let totalHurt = 0,
            posionHurt = 0,
            bloodHurt = 0,
            fireHurt = 0,
            iceHurt = 0;
        for (let i = fightAttrier.buffs.length - 1; i >= 0; i--) {
            if (fightAttrier.battleAttris.hp < 1) {
                break;
            }
            let buff = fightAttrier.buffs[i]
            if (!buff) {
                continue
            }
            let buffConfig = gameConfigHandle.configByID[buff.tid]

            if (buff.roundHurt) {
                let hurt = this.calcRoundHurt(fightAttrier, buff)
                if (buffConfig.buffType == BuffType.Poison) {
                    posionHurt += hurt
                } else if (buffConfig.buffType == BuffType.Blood) {
                    bloodHurt += hurt
                } else if (buffConfig.buffType == BuffType.Fire) {
                    fireHurt += hurt
                } else if (buffConfig.buffType == BuffType.Ice) {
                    iceHurt += hurt
                }

            }

            if (buff.round !== 0) {
                if (this.round >= (buff.round + buff.roundIndex - 1)) {
                    fightAttrier.buffs.splice(i, 1)
                }
            }
        }
        for (let i = fightAttrier.tempAttris.length - 1; i >= 0; i--) {
            let tempAttri = fightAttrier.tempAttris[i]
            if (!tempAttri) {
                continue
            }
            if (tempAttri.round && tempAttri.round > this.round) {
                fightAttrier.tempAttris.splice(i, 1)
            }
        }
        if (posionHurt > 0) {
            await this.decHp(fightAttrier, null, new DamageDataModel({ hurtType: HurtType.Poison, decHpName: '中毒', damage: posionHurt }))
            await this.setBattleTimeout(100)
        }
        if (bloodHurt > 0) {
            await this.decHp(fightAttrier, null, new DamageDataModel({ hurtType: HurtType.Blood, decHpName: '流血', damage: bloodHurt }))
            await this.setBattleTimeout(100)
        }
        if (fireHurt > 0) {
            await this.decHp(fightAttrier, null, new DamageDataModel({ hurtType: HurtType.Fire, decHpName: '灼烧', damage: fireHurt }))
            await this.setBattleTimeout(100)
        }
        if (iceHurt > 0) {
            await this.decHp(fightAttrier, null, new DamageDataModel({ hurtType: HurtType.Ice, decHpName: '冰冻', damage: iceHurt }))
            await this.setBattleTimeout(100)
        }

        fighterHandle.calcBattleFighterAttri(fightAttrier, this.aureoles)
        this.fighterNodeUpdate(fightAttrier.teamIndexID)
    }

    async calcBuffStatus(fightAttrier: FighterModel) {
        if (fightAttrier.battleAttris.hp > 0) {
            let posion = fightAttrier.status[BuffType.Poison] || 0
            let posionDeliver: FighterModel
            for (let buff of fightAttrier.buffs) {
                if (buff.stack > 0 || buff.round > 0) {
                    let buffConfig = gameConfigHandle.configByID[buff.tid]
                    if (buffConfig.buffType == BuffType.YiShang) {
                        buff.stack = buff.stack - 1
                        fightAttrier.status[buffConfig.BuffType] = buff.stack
                    } else if (buffConfig.buffType == BuffType.Poison) {
                        buff.stack = buff.stack - 1
                        if (buff.stack < 1) {
                            buff.stack = 1
                        }
                        posionDeliver = this.getFighterByTeamIndexID(buff.deliverIndex)
                        fightAttrier.status[buffConfig.buffType] = buff.stack
                    }
                }
            }

            if (posion) {
                let hurt = Math.floor(posionDeliver.battleAttris.attack * (20 + posion) / 100 * (1 + posionDeliver.battleAttris.skillHurtPer / 2 / 100))
                let damageData = new DamageDataModel()
                damageData.damage = hurt
                damageData.decHpName = "中毒"
                damageData.hurtType = HurtType.Poison
                damageData.skillIndex = -2
                await this.decHp(fightAttrier, posionDeliver, damageData)
            }
            fighterHandle.calcBattleFighterAttri(fightAttrier, this.aureoles)
            this.fighterNodeUpdate(fightAttrier.teamIndexID)
        }
    }

    calcRoundHurt(fightAttrier: FighterModel, buff: BuffModel) {
        let deliver = this.getFighterByTeamIndexID(buff.deliverIndex)
        let hurt = 0
        if (buff.roundHurt) {
            if (buff.roundHurt.attackHurtPer) {
                hurt += Math.floor(deliver.battleAttris.attack * buff.roundHurt.attackHurtPer / 100)
            }
            if (buff.roundHurt.maxHpPerHurt) {
                hurt += Math.floor(fightAttrier.battleAttris.maxHp * buff.roundHurt.maxHpPerHurt / 100)
            }
            if (buff.roundHurt.attackerHpHurtPer) {
                hurt += Math.floor(deliver.battleAttris.maxHp * buff.roundHurt.attackerHpHurtPer / 100)
            }
        }
        if (deliver.teamID == TeamID.Team1) {
            this.damageKillData.damage[deliver.tid] = (this.damageKillData.damage[deliver.tid] || 0) + hurt
            if (fightAttrier.battleAttris.hp < 1) {
                this.damageKillData.kill[deliver.tid] = (this.damageKillData.kill[deliver.tid] || 0) + 1
                // this.damageKillData.kill['all'] = (this.damageKillData.kill['all'] || 0) + 1
            }
        } else {
            this.enemyDamageData.damage[deliver.tid] = (this.enemyDamageData.damage[deliver.tid] || 0) + hurt
            if (fightAttrier.battleAttris.hp < 1) {
                this.enemyDamageData.kill[deliver.tid] = (this.enemyDamageData.kill[deliver.tid] || 0) + 1
                // this.enemyDamageData.kill['all'] = (this.enemyDamageData.kill['all'] || 0) + 1
            }
        }
        return hurt
    }

    isTeamAlive(teamID: TeamID) {
        let alive = false
        let team = this.getTeam(teamID)
        team.forEach(fighter => {
            if (fighter && fighter.battleAttris.hp >= 1) {
                alive = true
            }
        })
        if (teamID == TeamID.Team1 && this.altar1 && this.altar1.battleAttris.hp >= 1) {
            alive = true
        } else if (teamID == TeamID.Team2 && this.altar2 && this.altar2.battleAttris.hp >= 1) {
            alive = true
        }
        if (teamID == TeamID.Team2 && this.stage < this.maxStage) {
            alive = true
        }
        return alive
    }


    isNextStage(teamID: TeamID) {
        if (teamID == TeamID.Team2) {
            let alive = false
            let team = this.getTeam(teamID)
            team.forEach(fighter => {
                if (fighter && fighter.battleAttris.hp >= 1) {
                    alive = true
                }
            })
            if (this.stage < this.maxStage && alive == false) {
                return true
            }
        }
        return false
    }

    async nextStage(teamID) {
        await this.setBattleTimeout(500)
        let team = this.getTeam(teamID)
        for (let i = 0; i < team.length; i++) {
            let fighter = team[i]
            if (fighter) {
                this.disappearAnimation(fighter.teamIndexID, true)
            }
        }
        await this.setBattleTimeout(300)
        for (let i = 0; i < team.length; i++) {
            let fighter = team[i]
            if (fighter) {
                delete this.fighterNodes[fighter.teamIndexID]
            }
        }
        this.team2 = []
        this.stage += 1
        let monsterTeam = this.monsterHandle.createMonsters(this.rand)
        monsterTeam.team.forEach((fighter, i) => {
            if (fighter) {
                fighter.teamIndexID = this.teamIndexID++
                fighter.teamID = TeamID.Team2
                this.allQueue.push(fighter)
                this.battleQueue.push(fighter)
                this.team2[i] = fighter
                fighterHandle.calcSkills(fighter, this)
                fighter.battlePos = i
                this.statisticsData[fighter.teamIndexID] = { hurt: 0, cure: 0, recover: 0, beHurt: 0 }
                this.battleUpdate(1, fighter)
            }
        })
        this.battleQuqueSortBySpeed()
        this.battleUpdate(0)
        await this.setBattleTimeout(300)
    }

    calcHatred(teamID: TeamID, hatredDataConfig: any, lvl: number = 1, distanceBattlePos?: number): FighterModel[] {
        let opts = Object.assign({
            targetRankType: hatredDataConfig?.hartedData?.targetRankType || TargetRankType.Hatred,  //仇恨排序类型 0随机,1:按仇恨值排序,2:生命最多, 3:生命最少, 4:攻击力最高, 5:攻击力最低, 
            sortByWeight: false,  //仇恨值排序按照比重随机排序
            isDistance: true,  //是否根据距离排序
            battlePosHatredID: hatredDataConfig?.hartedData?.battlePosHatredID || hatredDataConfig?.battlePosHatredID || 1, // 1 优先前排 2 必须前排 3 后排优先 4 必须后排
            targetAmount: hatredDataConfig?.hartedData?.targetAmount || [1, 0], //目标数量
            range: hatredDataConfig?.hartedData?.range || null //范围
        }, hatredDataConfig)
        let { targetRankType, sortByWeight, isDistance, battlePosHatredID, targetAmount, range } = opts
        let defenders: FighterModel[] = []
        if (targetRankType == TargetRankType.Default || !targetRankType) {
            defenders = this.getFightersByRand(teamID, 0)
        } else if (targetRankType == TargetRankType.Hatred) { //按位置仇恨值排序
            let team = this.getTeam(teamID)
            let battlePosHatredConfig = gameConfigHandle.gameConfig.battle.battlePosHatredData[battlePosHatredID || 1]
            let hartreds = []
            let distanceBattlePosXY = null
            if (distanceBattlePos) {
                distanceBattlePosXY = this.getXY(distanceBattlePos)
            }
            let totalHatred = 0
            team.forEach(fighter => {
                if (fighter && fighter.battleAttris.hp >= 1) {
                    let { x, y } = this.getXY(fighter.battlePos)
                    let value = battlePosHatredConfig[y][x]
                    if (isDistance && distanceBattlePosXY) {
                        value -= Math.abs(distanceBattlePosXY.x - x) * 1 + y * 1
                    }
                    if (value < 1) {
                        value = 1
                    }
                    totalHatred += value
                    hartreds.push({
                        value: value,
                        fighter: fighter
                    })
                }
            })
            hartreds.sort((a1, a2) => {
                return a2.value - a1.value
            })
            if (sortByWeight) { //仇恨值排序按照比重随机排序
                for (let i = 0; i < hartreds.length; i++) {
                    let randValue = this.rand.intn(totalHatred)
                    let j = 0
                    while (j < hartreds.length) {
                        if (randValue <= hartreds[j].value) {
                            totalHatred -= hartreds[j].value
                            hartreds[j].value = 0
                            defenders.push(hartreds[j].fighter)
                            break
                        }
                        randValue -= hartreds[j].value
                        j += 1
                    }
                }
            } else {
                hartreds.forEach(item => {
                    defenders.push(item.fighter)
                })
            }
        } else if (targetRankType == TargetRankType.HgihHp) {
            defenders = this.getFightersByAttriRank(teamID, 'hp', 1)
        } else if (targetRankType == TargetRankType.LowHp) {
            defenders = this.getFightersByAttriRank(teamID, 'hp', 0)
        } else if (targetRankType == TargetRankType.HighAttack) {
            defenders = this.getFightersByAttriRank(teamID, 'attack', 1)
        } else if (targetRankType == TargetRankType.LowAttack) {
            defenders = this.getFightersByAttriRank(teamID, 'attack', 0)
        } else if (targetRankType == TargetRankType.HighSpeed) {
            defenders = this.getFightersByAttriRank(teamID, 'speed', 1)
        } else if (targetRankType == TargetRankType.LowSpeed) {
            defenders = this.getFightersByAttriRank(teamID, 'speed', 0)
        } else if (targetRankType == TargetRankType.HgihMaxHp) {
            defenders = this.getFightersByAttriRank(teamID, 'maxHp', 1)
        } else if (targetRankType == TargetRankType.LowMaxHp) {
            defenders = this.getFightersByAttriRank(teamID, 'maxHp', 0)
        }

        if (defenders.length == 0) {
            if (teamID == TeamID.Team1 && this.altar1 && this.altar1.battleAttris.hp >= 1) {
                return [this.altar1]
            } else if (teamID == TeamID.Team2 && this.altar2 && this.altar2.battleAttris.hp >= 1) {
                return [this.altar2]
            } else {
                return []
            }
        }

        if (range) { //范围
            let defender = defenders[0]
            let { x, y } = this.getXY(defender.battlePos)
            let { maxX, maxY } = this.getMaxXY(teamID)
            let rangey = [y - Math.floor(range[1] / 2) + (1 - range[1] % 2), y + Math.floor(range[1] / 2)]
            if (range[1] % 2 == 0) {
                if (this.rand.intn(100) < 50) {
                    rangey = [rangey[0] - 1, rangey[1] - 1]
                }
            }

            if (rangey[1] >= maxY) {
                rangey[0] = rangey[0] - (rangey[1] - maxY + 1)
                rangey[1] = maxY - 1
                if (rangey[0] < 0) {
                    rangey[0] = 0
                }
            }
            if (rangey[0] < 0) {
                rangey[1] = rangey[1] + (0 - rangey[0])
                rangey[0] = 0
                if (rangey[1] >= maxY) {
                    rangey[1] = maxY - 1
                }
            }
            let rangex = [x - Math.floor(range[0] / 2) + (1 - range[0] % 2), x + Math.floor(range[0] / 2)]
            if (range[0] % 2 == 0) {
                if (this.rand.intn(100) < 50) {
                    rangex = [rangex[0] - 1, rangex[1] - 1]
                }
            }
            if (rangex[1] >= maxX) {
                rangex[0] = rangex[0] - (rangex[1] - maxX + 1)
                rangex[1] = maxX - 1
                if (rangex[0] < 0) {
                    rangex[0] = 0
                }
            }
            if (rangex[0] < 0) {
                rangex[1] = rangex[1] + (0 - rangex[0])
                rangex[0] = 0
                if (rangex[1] >= maxX) {
                    rangex[1] = maxX - 1
                }
            }
            let _defenderTeams = []
            let team = this.getTeam(teamID)
            for (let x = rangex[0]; x <= rangex[1]; x++) {
                for (let y = rangey[0]; y <= rangey[1]; y++) {
                    let battlePos = this.getBattlePos(x, y)
                    let defender = team[battlePos]
                    if (defender && defender.battleAttris.hp >= 1) {
                        _defenderTeams.push(defender)
                    }
                }
            }
            return _defenderTeams
        } else { //数量
            let _targetAmount = utils.getIncValues(targetAmount || [1, 0], lvl)
            let _defenderTeams = defenders.slice(0, _targetAmount || 1)
            return _defenderTeams
        }

    }

    //获得攻击间隔
    getAttackInterval(attackSpeed) {
        let base = 100
        if (attackSpeed <= 100) {
            base = attackSpeed
        }
        if (attackSpeed > 100) {
            let value1 = (attackSpeed - 100) * 0.35
            value1 = value1 > 140 ? 140 : value1
            base += value1
        }

        if (attackSpeed > 500) {
            let value2 = (attackSpeed - 500) * 0.2
            base += value2
        }
        let interval = 5000 / base * 100
        return interval
    }

    battleQuqueSortBySpeed = () => {
        let newBattleQueue = []
        this.battleQueue.forEach(item => {
            if (item && (item.unitType == UnitType.Partner || item.battleAttris.hp >= 1)) {
            }
        })
        this.battleQueue.sort((a1, a2) => {
            return a2.battleAttris.speed - a1.battleAttris.speed
        })
    }

    getSkill = (attacker: FighterModel): FighterSkillModel => {
        let skill = attacker.angerSkill
        if (!skill) {
            return null
        }

        let mp = gameConfigHandle.gameConfig.battle.skillNeedAnger * (1 - attacker.battleAttris.skillReduceAngerPer / 100)
        console.log('anger=', mp)
        if (attacker.battleAttris.anger >= mp) {
            attacker.battleAttris.anger = 0
            return skill
        }
        return null
    }

    getXY(battlePos) {
        let y = Math.floor(battlePos / this.maxCol)
        let x = Math.floor(battlePos % this.maxCol)
        return { x, y }
    }

    getMaxXY(teamIndexID: TeamID) {
        return { maxX: this.maxCol, maxY: this.maxRow }
    }
    getBattlePos(x: number, y: number) {
        return x + y * this.maxCol
    }

    getFighterByBattlePos(teamID: TeamID, x, y) {
        let team = this.getTeam(teamID)
        let { maxX, maxY } = this.getMaxXY(teamID)

        if (x > maxX || x < 0 || y > maxY || y < 0) {
            return null
        }
        return team[this.getBattlePos(x, y)]
    }

    //随机获取伙伴
    getFightAttrisByHpPer(teamID: TeamID, amount: number): FighterModel[] {
        var team: FighterModel[] = this.getTeam(teamID)

        let value = []
        for (let i in team) {
            let t = team[i]
            if (t && t.battleAttris.hp >= 1) {
                value.push({
                    HpPerValue: Math.floor(t.battleAttris.maxHp * 100 / t.battleAttris.hp),
                    Partner: t
                })
            }
        }
        value.sort((a1, a2) => {
            return a1.hpPerValue <= a2.hpPerValue ? 1 : -1
        })
        let fightAttriTeam: FighterModel[] = []
        for (let i = 0; i < amount && i < value.length; i++) {
            fightAttriTeam.push(value[i].Partner)
        }
        return fightAttriTeam
    }

    getTeam(teamID: TeamID) {
        if (teamID == TeamID.Team2) {
            return this.team2
        } else {
            return this.team1
        }
    }

    getOpponentTeam(teamID: TeamID) {
        if (teamID == TeamID.Team1) {
            return this.team2
        } else {
            return this.team1
        }
    }

    getOpponentTeamID(teamID: TeamID) {
        if (teamID == TeamID.Team1) {
            return TeamID.Team2
        } else {
            return TeamID.Team1
        }
    }
    getTeamLength(teamID: TeamID) {
        if (teamID == TeamID.Team1) {
            return this.team1Length
        } else {
            return this.team2Length
        }
    }



    getFighterByTeamIndexID(teamIndexID: number) {
        for (let i = 0; i < this.allQueue.length; i++) {
            let fighter = this.allQueue[i]
            if (fighter.teamIndexID == teamIndexID) {
                return fighter
            }
        }
        return null
    }

    getAltarFighterByTeamIndexID(teamID: TeamID) {
        if (teamID == TeamID.Team1) {
            return this.altar1
        } else {
            return this.altar2
        }
    }

    fighterNodeUpdate = (teamIndexID: number, buff?: BuffModel) => {
        if (this.update) {
            if (this.fighterNodes[teamIndexID]) {
                this.fighterNodes[teamIndexID].update(buff)
            }
        }
    }
    battleUpdate = (type, value?) => {
        if (this.update) {
            if (type == 0) {
                this.update(0, {
                    current: this.monsterAmount - this.monsterAliveAmount, max: this.monsterAmountMax,
                    round: this.round, stage: this.stage, maxStage: this.maxStage
                })
            } else {
                if (this.timeCoe !== 0) {
                    this.update(type, value)
                }
            }
        }
    }
    beAttackAnimation = async (teamIndexID: number, damageData: DamageDataModel, animationDelay: number = 0) => {
        if (this.update && this.fighterNodes[teamIndexID] && this.timeCoe !== 0 && this.timeCoe < 20) {

            this.fighterNodes[teamIndexID].beAttackAnimation(damageData, animationDelay)
        }
    }

    startAttackAnimation(id, duration) {
        if (this.update && this.timeCoe !== 0 && this.timeCoe < 20) {
            if (!this.fighterNodes[id]) {
            } else {
                this.fighterNodes[id].startAttackAnimation(duration)
            }
        }
    }


    attackAnimation = async (teamIndexID: number, skillID?: number) => {
        if (this.update && this.timeCoe !== 0 && this.timeCoe < 20) {

            if (this.fighterNodes[teamIndexID]) {
                await this.fighterNodes[teamIndexID].attackAnimation(skillID)
            }
        }
    }

    tipAnimation = async (teamIndexID: number, str: string, type: number = 0) => {
        if (this.update && this.fighterNodes[teamIndexID] && this.timeCoe !== 0 && this.timeCoe < 20) {
            this.fighterNodes[teamIndexID].tipAnimation(str, type)
        }
    }
    recoverAnimation = async (teamIndexID: number, value: number, addType: AnimationValueType = AnimationValueType.RecoverHp, str: string = '') => {
        if (this.update && this.fighterNodes[teamIndexID]) {
            this.fighterNodes[teamIndexID].recoverAnimation(value, addType, str)
        }
    }
    recoverMpAnimation = async (teamIndexID: number, value: number, str: string, isCrit: boolean = false) => {
        if (this.update && this.fighterNodes[teamIndexID] && this.timeCoe !== 0 && this.timeCoe < 20) {
            this.fighterNodes[teamIndexID].recoverMpAnimation(value, str || '恢复', isCrit)
        }
    }
    startUseSkillAnimation(teamIndexID: number, skillIndex, duration) {
        if (this.update && this.fighterNodes[teamIndexID] && this.timeCoe !== 0 && this.timeCoe < 20) {
            this.fighterNodes[teamIndexID].startUseSkillAnimation(skillIndex, duration)
        }
    }
    useSkillAnimation = async (teamIndexID: number, skillIndex) => {
        if (this.update && this.fighterNodes[teamIndexID] && this.timeCoe !== 0 && this.timeCoe < 20) {
            this.fighterNodes[teamIndexID].useSkillAnimation(skillIndex)
        }
    }
    monsterLvlUpAnimation = async (teamIndexID: number) => {
        if (this.update && this.fighterNodes[teamIndexID] && this.timeCoe !== 0 && this.timeCoe < 20) {
            this.fighterNodes[teamIndexID].monsterLvlUpAnimation()
        }
    }
    disappearAnimation = async (teamIndexID: number, isDestroy: boolean = false) => {
        if (this.update && this.fighterNodes[teamIndexID] && this.timeCoe !== 0 && this.timeCoe < 20) {
            await this.fighterNodes[teamIndexID].disappearAnimation(isDestroy)
        }
    }

    doubleAnimation = async (teamIndexID: number, amount: number) => {
        if (this.update && this.fighterNodes[teamIndexID] && this.timeCoe !== 0 && this.timeCoe < 20) {
            await this.fighterNodes[teamIndexID].doubleAnimation(amount)
        }
    }

    addMonsterAnimation = async (teamIndexID: number) => {
        if (this.update && this.fighterNodes[teamIndexID] && this.timeCoe !== 0 && this.timeCoe < 20) {
            await this.fighterNodes[teamIndexID].addMonsterAnimation()
        }
    }


    skillTipAnimation(teamIndexID: number, skillIndex, str) {
        if (this.update && this.fighterNodes[teamIndexID] && this.timeCoe !== 0 && this.timeCoe < 20) {
            this.fighterNodes[teamIndexID].skillTipAnimation(skillIndex, str)
        }
    }

    fighterBgGlimmerAnimation = (battlePos, skillTID?: number) => {
        if (this.update && this.timeCoe !== 0 && this.timeCoe < 20) {
            if (this.fighterBgNodes[battlePos]) {
                this.fighterBgNodes[battlePos].glimmer(skillTID)
            }
        }
    }

    setBattleTimeout(timeout: number, cb?: (number) => void, disableRoundTime: boolean = false): Promise<number> {
        if (!disableRoundTime) {
            this.totalRoundTime += timeout / (this.timeCoe || 1)
            if (this.timeCoe > 1) {
                this.speedRunTime += timeout / (this.timeCoe || 1)
            }
        }

        return new Promise(async resolve => {
            let duration = 0
            if (this.update && this.timeCoe !== 0 && this.timeCoe < 20) {
                duration = timeout

                let timerID = this.timerHandle.setTimeout(() => {
                    delete this.battleTimer[timerID]

                    resolve(timerID)
                }, duration);

                this.battleTimer[timerID] = timerID
                cb && cb(timerID)
            } else {
                resolve(null)
            }
        })
    }

    clearBattleTimer(timerID) {
        if (this.battleTimer[timerID]) {
            this.timerHandle.clear(timerID)
            delete this.battleTimer[timerID]
        }
    }

    clearBattleAllTimer() {
        this.clearTimeLine()
        for (let timerID of utils.keys(this.battleTimer)) {
            this.timerHandle.clear(Number(timerID))
            delete this.battleTimer[timerID]
        }
        this.timerHandle.stop()
    }

    getPartners(teamID: TeamID, amount: number, excludeTeamIndexID?: number) {
        let team = this.getTeam(teamID)
        let partners: FighterModel[] = []
        for (let i = 0; i < team.length; i++) {
            let t = team[i]
            if (t && t.battleAttris.hp >= 1 && t.teamIndexID != excludeTeamIndexID) {
                partners.push(t)
            }
        }
        if (amount) {
            return utils.getRandomArrayNoRepeat(partners, amount, this.rand)
        } else {
            return partners
        }
    }

    getFightersByRand(teamID: TeamID, amount: number, excludeTeamIndexID?: number) {
        let team = this.getTeam(teamID)
        let partners: FighterModel[] = []
        for (let i = 0; i < team.length; i++) {
            let t = team[i]
            if (t && t.battleAttris.hp >= 1 && t.teamIndexID != excludeTeamIndexID) {
                partners.push(t)
            }
        }
        if (amount) {
            return utils.getRandomArrayNoRepeat(partners, amount, this.rand)
        } else {
            return utils.getRandomArrayNoRepeat(partners, partners.length, this.rand)
        }
    }

    getFightersByLowHp(teamID: number, amount?: number, excludeTeamIndexID?: number) {
        let team = this.getTeam(teamID)
        let fighterTeam: FighterModel[] = []
        team.forEach(fighter => {
            if (fighter && fighter.battleAttris.hp >= 1 && fighter.teamIndexID != excludeTeamIndexID) {
                fighterTeam.push(fighter)
            }
        })
        fighterTeam.sort((a1, a2) => {
            return a1.battleAttris.hp - a2.battleAttris.hp
        })
        if (amount) {
            return fighterTeam.slice(0, amount)
        } else {
            return fighterTeam
        }

    }
    getFightersByHighHp(teamID: number, amount?: number, excludeTeamIndexID?: number) {
        let team = this.getTeam(teamID)
        let fighterTeam: FighterModel[] = []
        team.forEach(fighter => {
            if (fighter && fighter.battleAttris.hp >= 1 && fighter.teamIndexID != excludeTeamIndexID) {
                fighterTeam.push(fighter)
            }
        })
        fighterTeam.sort((a1, a2) => {
            return a2.battleAttris.hp - a1.battleAttris.hp
        })
        if (amount) {
            return fighterTeam.slice(0, amount)
        } else {
            return fighterTeam
        }
    }
    getFightersByHighAttack(teamID: number, amount?: number, excludeTeamIndexID?: number) {
        let team = this.getTeam(teamID)
        let fighterTeam: FighterModel[] = []
        team.forEach(fighter => {
            if (fighter && fighter.battleAttris.hp >= 1 && fighter.teamIndexID != excludeTeamIndexID) {
                fighterTeam.push(fighter)
            }
        })
        fighterTeam.sort((a1, a2) => {
            return a2.battleAttris.attack - a1.battleAttris.attack
        })
        if (amount) {
            return fighterTeam.slice(0, amount)
        } else {
            return fighterTeam
        }
    }
    getFightersByLowAttack(teamID: number, amount?: number, excludeTeamIndexID?: number) {
        let team = this.getTeam(teamID)
        let fighterTeam: FighterModel[] = []
        team.forEach(fighter => {
            if (fighter && fighter.battleAttris.hp >= 1 && fighter.teamIndexID != excludeTeamIndexID) {
                fighterTeam.push(fighter)
            }
        })
        fighterTeam.sort((a1, a2) => {
            return a1.battleAttris.attack - a2.battleAttris.attack
        })
        if (amount) {
            return fighterTeam.slice(0, amount)
        } else {
            return fighterTeam
        }
    }

    getFightersByAttriRank(teamID: number, attriName: string, rankType: number, amount?: number, excludeTeamIndexID?: number) {
        let team = this.getTeam(teamID)
        let fighterTeam: FighterModel[] = []
        team.forEach(fighter => {
            if (fighter && fighter.battleAttris.hp >= 1 && fighter.teamIndexID != excludeTeamIndexID) {
                fighterTeam.push(fighter)
            }
        })
        fighterTeam.sort((a1, a2) => {
            if (rankType == 0) { // 0升序,从小到大
                return a1.battleAttris[attriName] - a2.battleAttris[attriName]
            } else { // 降序
                return a2.battleAttris[attriName] - a1.battleAttris[attriName]
            }
        })
        if (amount) {
            return fighterTeam.slice(0, amount)
        } else {
            return fighterTeam
        }
    }


    getFightersByTargetType(trigger, targetType: TargetType, targetAmount, rankType: TargetRankType = TargetRankType.Default, stakeholder?: FighterModel): FighterModel[] {
        let fighters: FighterModel[] = []
        if (targetType == TargetType.Trigger || !targetType) {
            fighters = [trigger]
        } else if (targetType == TargetType.Stakeholder && stakeholder) {
            fighters = [stakeholder]
        } else if (targetType == TargetType.MyTeam) {
            let team = this.getTeam(trigger.teamID)
            team.forEach(fighter => {
                if (fighter && fighter.battleAttris.hp >= 1) {
                    fighters.push(fighter)
                }
            })
        } else if (targetType == TargetType.OppentTeam) {
            let team = this.getTeam(this.getOpponentTeamID(trigger.teamID))
            team.forEach(fighter => {
                if (fighter && fighter.battleAttris.hp >= 1) {
                    fighters.push(fighter)
                }
            })
        } else if (targetType == TargetType.Enemys) {
            let opponentTeamID = this.getOpponentTeamID(trigger.teamID)
            if (!rankType) {
                fighters = this.getFightersByRand(opponentTeamID, targetAmount)
            } else if (rankType == TargetRankType.HgihHp) {
                fighters = this.getFightersByAttriRank(opponentTeamID, 'hp', 1, targetAmount)
            } else if (rankType == TargetRankType.LowHp) {
                fighters = this.getFightersByAttriRank(opponentTeamID, 'hp', 0, targetAmount)
            } else if (rankType == TargetRankType.HgihMaxHp) {
                fighters = this.getFightersByAttriRank(opponentTeamID, 'maxHp', 1, targetAmount)
            } else if (rankType == TargetRankType.LowMaxHp) {
                fighters = this.getFightersByAttriRank(opponentTeamID, 'maxHp', 0, targetAmount)
            } else if (rankType == TargetRankType.HighAttack) {
                fighters = this.getFightersByAttriRank(opponentTeamID, 'attack', 1, targetAmount)
            } else if (rankType == TargetRankType.LowAttack) {
                fighters = this.getFightersByAttriRank(opponentTeamID, 'attack', 0, targetAmount)
            } else if (rankType == TargetRankType.HighSpeed) {
                fighters = this.getFightersByAttriRank(opponentTeamID, 'speed', 1, targetAmount)
            } else if (rankType == TargetRankType.LowSpeed) {
                fighters = this.getFightersByAttriRank(opponentTeamID, 'speed', 0, targetAmount)
            }
        } else if (targetType == TargetType.Partners) {
            if (!rankType) {
                fighters = this.getFightersByRand(trigger.teamID, targetAmount)
            } else if (rankType == TargetRankType.HgihHp) {
                fighters = this.getFightersByAttriRank(trigger.teamID, 'hp', 1, targetAmount)
            } else if (rankType == TargetRankType.LowHp) {
                fighters = this.getFightersByAttriRank(trigger.teamID, 'hp', 0, targetAmount)
            } else if (rankType == TargetRankType.HgihMaxHp) {
                fighters = this.getFightersByAttriRank(trigger.teamID, 'maxHp', 1, targetAmount)
            } else if (rankType == TargetRankType.LowMaxHp) {
                fighters = this.getFightersByAttriRank(trigger.teamID, 'maxHp', 0, targetAmount)
            } else if (rankType == TargetRankType.HighAttack) {
                fighters = this.getFightersByAttriRank(trigger.teamID, 'attack', 1, targetAmount)
            } else if (rankType == TargetRankType.LowAttack) {
                fighters = this.getFightersByAttriRank(trigger.teamID, 'attack', 0, targetAmount)
            } else if (rankType == TargetRankType.HighSpeed) {
                fighters = this.getFightersByAttriRank(trigger.teamID, 'speed', 1, targetAmount)
            } else if (rankType == TargetRankType.LowSpeed) {
                fighters = this.getFightersByAttriRank(trigger.teamID, 'speed', 0, targetAmount)
            }

        } else if (targetType == TargetType.PartnersNoMySelf) {
            if (!rankType) {
                fighters = this.getFightersByRand(trigger.teamID, targetAmount, trigger.teamIndexID)
            } else if (rankType == TargetRankType.HgihHp) {
                fighters = this.getFightersByAttriRank(trigger.teamID, 'hp', 1, targetAmount, trigger.teamIndexID)
            } else if (rankType == TargetRankType.LowHp) {
                fighters = this.getFightersByAttriRank(trigger.teamID, 'hp', 0, targetAmount, trigger.teamIndexID)
            } else if (rankType == TargetRankType.HgihMaxHp) {
                fighters = this.getFightersByAttriRank(trigger.teamID, 'maxHp', 1, targetAmount, trigger.teamIndexID)
            } else if (rankType == TargetRankType.LowMaxHp) {
                fighters = this.getFightersByAttriRank(trigger.teamID, 'maxHp', 0, targetAmount, trigger.teamIndexID)
            } else if (rankType == TargetRankType.HighAttack) {
                fighters = this.getFightersByAttriRank(trigger.teamID, 'attack', 1, targetAmount, trigger.teamIndexID)
            } else if (rankType == TargetRankType.LowAttack) {
                fighters = this.getFightersByAttriRank(trigger.teamID, 'attack', 0, targetAmount, trigger.teamIndexID)
            } else if (rankType == TargetRankType.HighSpeed) {
                fighters = this.getFightersByAttriRank(trigger.teamID, 'speed', 1, targetAmount, trigger.teamIndexID)
            } else if (rankType == TargetRankType.LowSpeed) {
                fighters = this.getFightersByAttriRank(trigger.teamID, 'speed', 0, targetAmount, trigger.teamIndexID)
            }
        }
        return fighters
    }

    addTimeLine(tl) {
        let timelineIndex = this.timelineIndex++
        this.timelineData[timelineIndex] = tl
        tl.addLabel("timelineIndex", timelineIndex)
    }
    removeTimeLine(tl) {
        if (tl) {
            tl.kill()
            if (tl.getLabel) {
                let timelineIndex = tl.getLabel("timelineIndex")
                if (timelineIndex) {
                    delete this.timelineData[timelineIndex]
                }
            }

        }
    }
    clearTimeLine() {
        utils.values(this.timelineData).forEach((tl: any) => {
            tl.kill()
        })
        this.timelineData = {}
        this.timelineIndex = 0
    }
}

